#pragma once

#include "core/color.h"

#include <vector>

namespace renderit
{
	namespace image
	{
		class algorithm_connected_area;

		enum ImageEdgeDirection {
			EDir_Left = 1 << 0,
			EDir_Right = 1 << 1,
			EDir_Up = 1 << 2,
			EDir_Down = 1 << 3
		};

		typedef bool(*func_is_equal)(core::color4b* data1, core::color4b* data2);
		typedef bool(*func_is_edge)(algorithm_connected_area* c, int row1, int line1, int row2, int line2);
		typedef bool(*func_correct_edge)(algorithm_connected_area* c, int row1, int line1, int row2, int line2);

		class algorithm_connected_area
		{
		public:
			algorithm_connected_area(core::color4b* data, int width, int height);

		public:
			virtual ~algorithm_connected_area();

		public:
			void run(func_is_equal equal_func, func_is_edge is_edge_func);

		public:
			struct _pixel_data {
				int group;
				int is_edge;

				_pixel_data() : group(0), is_edge(0) {}
			};

			_pixel_data* pixel_data_;
			int width_;
			int height_;

			int max_group_id_;

			std::vector<int> parents_;

			core::color4b* color_data_;
			func_is_equal equal_func_;
			func_is_edge is_edge_func_;
			func_correct_edge correct_edge_func_;

		private:
			int find_root_group(int group, int& depth);
			void add_equal_pair(int group1, int group2);
			bool is_equal_group(int group1, int group2);

			void pass1_collect_group();
			void pass2_merge_group();
			void pass3_check_edge();
		};
	}
}